import os
import time
import threading
import pyautogui
import shutil
import keyboard
from datetime import datetime
from PIL import ImageGrab
import tkinter as tk
import uuid

class ApplicationController:
    """应用程序控制器"""
    def __init__(self, view):
        self.view = view
        self.model = None  # 会在main.py中设置
        self.stop_event = threading.Event()
        self.recording = False
        self.screenshot_window = None
        self.selection_start = None
        self.selection_rect = None
        self.clipboard = None
        self.undo_stack = []  # 新增撤销栈

    def new_project(self):
        """创建新的宏工程"""
        # 如果已有工程，询问是否保存
        if self.model and self.model.current_project and self.model.get_macro_items():
            response = self.view.show_message("保存", "是否保存当前宏工程?", "yesnocancel")
            if response is None:  # 取消
                return
            if response:  # 是
                if not self.save_project():
                    return
        
        # 创建新工程
        self.model.new_project()
        self.view.update_edit_list(self.model.get_macro_items())
        self.view.update_macro_list(self.model.get_macro_items())
        self.view.log("创建了新的宏工程")

    def open_project(self):
        """打开宏工程"""
        # 如果已有工程，询问是否保存
        if self.model and self.model.current_project and self.model.get_macro_items():
            response = self.view.show_message("保存", "是否保存当前宏工程?", "yesnocancel")
            if response is None:  # 取消
                return
            if response:  # 是
                if not self.save_project():
                    return
        
        # 选择文件
        file_path = self.view.ask_file_path(
            "打开宏工程",
            [("宏工程文件", "*.json"), ("所有文件", "*.*")]
        )
        
        if file_path and self.model.open_project(file_path):
            self.view.update_edit_list(self.model.get_macro_items())
            self.view.update_macro_list(self.model.get_macro_items())
            self.view.update_recent_menu(self.model.recent_projects)
            self.view.log(f"打开了宏工程: {os.path.basename(file_path)}")

    def save_project(self):
        """保存宏工程"""
        if not self.model or not self.model.current_project:
            self.view.show_message("错误", "没有打开的宏工程", "error")
            return False
            
        # 如果还没有保存路径，使用另存为
        if not self.model.current_project.file_path:
            return self.save_project_as()
            
        # 保存工程
        if self.model.save_project():
            self.view.log(f"保存了宏工程: {os.path.basename(self.model.current_project.file_path)}")
            return True
        return False

    def save_project_as(self):
        """另存为宏工程"""
        if not self.model or not self.model.current_project:
            self.view.show_message("错误", "没有打开的宏工程", "error")
            return False
            
        file_path = self.view.ask_file_path(
            "保存宏工程",
            [("宏工程文件", "*.json"), ("所有文件", "*.*")],
            save=True
        )
        
        if file_path:
            if not file_path.endswith(".json"):
                file_path += ".json"
                
            if self.model.save_project(file_path):
                self.model.add_to_recent_projects(file_path)
                self.view.update_recent_menu(self.model.recent_projects)
                self.view.log(f"另存宏工程为: {os.path.basename(file_path)}")
                return True
        return False

    def open_recent_project(self, file_path):
        """打开最近的宏工程"""
        if os.path.exists(file_path) and self.model.open_project(file_path):
            self.view.update_edit_list(self.model.get_macro_items())
            self.view.update_macro_list(self.model.get_macro_items())
            self.view.log(f"打开了最近的宏工程: {os.path.basename(file_path)}")

    def switch_mode(self, mode):
        """切换应用模式"""
        self.view.mode_var.set(mode)  # 修复：同步单选按钮状态
        self.view.switch_mode(mode)

    def update_macro_editor(self):
        """更新宏命令编辑器"""
        macro_type = self.view.macro_type.get()
        self.view.update_macro_editor(macro_type)

    def on_macro_selected(self, event):
        """处理宏命令选中事件"""
        listbox = self.view.edit_listbox
        selected = listbox.curselection()
        
        if not selected:
            self.view.show_macro_properties(None)
            return
            
        index = selected[0]
        macro_item = self.model.get_macro_item(index)
        self.view.show_macro_properties(macro_item)

    def add_macro_to_list(self):
        """添加宏命令到列表"""
        if not self.model.current_project:
            response = self.view.show_message("提示", "没有打开的宏工程，是否创建新工程？", "yesno")
            if response:
                self.new_project()
            else:
                return
        
        macro_type = self.view.macro_type.get()
        kwargs = {}
        
        if macro_type == "keyboard":
            kwargs["key"] = self.view.keyboard_key.get()
            kwargs["action_type"] = self.view.keyboard_action.get()
            
        elif macro_type == "text":
            kwargs["content"] = self.view.text_content.get()
            
        elif macro_type == "mouse_move":
            kwargs["x"] = self.view.mouse_x.get()
            kwargs["y"] = self.view.mouse_y.get()
            
        elif macro_type == "mouse_move_image":
            image_path = self.view.image_path.get()
            if not image_path:
                self.view.show_message("警告", "请选择图片文件", "warning")
                return
                
            kwargs["src"] = image_path
            kwargs["grayscale"] = self.view.image_grayscale.get()
            kwargs["confidence"] = self.view.image_confidence.get()
            
        elif macro_type == "mouse":
            kwargs["button"] = self.view.mouse_button.get()
            kwargs["action_type"] = self.view.mouse_action.get()
            
        elif macro_type == "scroll":
            kwargs["amount"] = self.view.scroll_amount.get()
            
        elif macro_type == "wait":
            kwargs["milliseconds"] = self.view.wait_time.get()
            
        elif macro_type == "wait_key":
            kwargs["key"] = self.view.wait_key.get()
        
        # 添加宏命令
        item = self.model.add_macro_item(macro_type, **kwargs)
        if item:
            self.update_edit_list()
            self.update_macro_list()
            self.view.log(f"添加了宏命令: {item.get_display_text()}")

    def update_edit_list(self):
        """更新编辑列表"""
        items = self.model.get_macro_items()
        self.view.update_edit_list(items)

    def update_macro_list(self):
        """更新宏列表"""
        items = self.model.get_macro_items()
        self.view.update_macro_list(items)

    def move_item_up(self):
        """上移选中项"""
        selected = self.view.edit_listbox.curselection()
        if not selected:
            return
            
        index = selected[0]
        if index > 0:
            self.model.move_macro_item(index, index - 1)
            self.update_edit_list()
            self.update_macro_list()
            self.view.edit_listbox.selection_set(index - 1)

    def move_item_down(self):
        """下移选中项"""
        selected = self.view.edit_listbox.curselection()
        if not selected:
            return
            
        index = selected[0]
        items = self.model.get_macro_items()
        if index < len(items) - 1:
            self.model.move_macro_item(index, index + 1)
            self.update_edit_list()
            self.update_macro_list()
            self.view.edit_listbox.selection_set(index + 1)

    def delete_selected_item(self):
        """删除选中项"""
        # 根据当前模式选择对应的列表
        if self.view.mode_var.get() == "edit":
            listbox = self.view.edit_listbox
            selected = listbox.curselection()
            if not selected:
                return
                
            # 编辑模式只处理单选
            index = selected[0]
            item = self.model.get_macro_item(index)
            if item:
                self.model.remove_macro_item(item.id)
                self.update_edit_list()
                self.update_macro_list()
                self.view.log(f"删除了宏命令: {item.get_display_text()}")

    def get_current_mouse_pos(self):
        """获取当前鼠标位置"""
        x, y = pyautogui.position()
        self.view.mouse_x.set(x)
        self.view.mouse_y.set(y)
        self.view.log(f"获取鼠标位置: ({x}, {y})")

    def browse_image_file(self):
        """浏览图片文件"""
        file_path = self.view.ask_file_path(
            "选择图片",
            [("图片文件", "*.png;*.jpg;*.jpeg;*.bmp"), ("所有文件", "*.*")]
        )
        
        if file_path:
            self.view.image_path.set(file_path)
            self.update_image_preview(None, None, None)  # 更新预览

    def update_image_preview(self, *args):
        """更新图片预览"""
        file_path = self.view.image_path.get()
        self.view.update_image_preview(file_path)

    def capture_image_for_macro(self):
        """截取图片用于宏命令"""
        def on_press(event):
            self.selection_start = (event.x, event.y)
            self.selection_rect = None

        def on_drag(event):
            if self.selection_rect:
                self.canvas.delete(self.selection_rect)
            self.selection_rect = self.canvas.create_rectangle(
                self.selection_start[0], self.selection_start[1],
                event.x, event.y,
                outline="red", width=2
            )

        def on_release(event):
            # 确保截图窗口关闭
            if self.screenshot_window:
                self.screenshot_window.destroy()
                self.screenshot_window = None

            # 计算截图区域
            x1, y1 = self.selection_start
            x2, y2 = event.x, event.y
            x1, y1 = min(x1, x2), min(y1, y2)
            x2, y2 = max(x1, x2), max(y1, y2)

            # 确保区域有效
            if x2 - x1 > 10 and y2 - y1 > 10:
                # 截取屏幕
                screenshot = ImageGrab.grab(bbox=(x1, y1, x2, y2))
                
                # 保存图片
                timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
                image_path = os.path.join(self.model.image_dir, f"screenshot_{timestamp}.png")
                screenshot.save(image_path)
                
                # 更新视图
                self.view.image_path.set(image_path)
                self.update_image_preview(None, None, None)
                self.view.log(f"截取图片保存到: {os.path.basename(image_path)}")

        # 创建截图窗口
        self.screenshot_window, self.canvas = self.view.create_screenshot_window(
            on_press, on_drag, on_release
        )

    def open_screenshot_tool(self):
        """打开截图工具"""
        self.capture_image_for_macro()

    def start_recording(self):
        """开始录制宏"""
        if self.recording:
            self.view.show_message("提示", "已经在录制中", "info")
            return
            
        self.recording = True
        self.view.log("开始录制宏...")
        # 这里可以添加实际的录制逻辑

    def stop_recording(self):
        """停止录制宏"""
        if not self.recording:
            return
            
        self.recording = False
        self.view.log("停止录制宏")
        # 这里可以添加停止录制的逻辑

    def start_execution(self):
        """开始执行宏"""
        if not self.model or not self.model.current_project or not self.model.get_macro_items():
            self.view.show_message("错误", "没有可执行的宏命令", "error")
            return

        # 清除停止标志，允许执行
        self.stop_event.clear()

        # 读取循环选项
        self.loop_enabled = getattr(self.view, "loop_var", None) and self.view.loop_var.get()

        # 更新UI状态
        self.view.run_button.config(state="disabled")
        self.view.stop_button.config(state="normal")
        self.view.log("开始执行宏...")

        # 在新线程中执行宏，避免阻塞UI
        execution_thread = threading.Thread(target=self._execute_macro)
        execution_thread.start()

    def stop_execution(self):
        """停止执行宏"""
        if not self.stop_event.is_set():
            self.stop_event.set()
            self.view.log("正在停止宏执行...")

    def _execute_macro(self):
        """执行宏命令（内部方法）"""
        try:
            while True:
                items = self.model.get_macro_items()
                for i, item in enumerate(items):
                    if self.stop_event.is_set():
                        self.view.log("宏执行已停止")
                        return

                    # 更新当前执行项的UI显示
                    self.view.macro_listbox.selection_clear(0, tk.END)
                    self.view.macro_listbox.selection_set(i)
                    self.view.macro_listbox.see(i)

                    # 新增：显示当前执行项属性
                    self.view.show_run_macro_properties(item)

                    # 执行宏命令
                    success = item.execute(
                        log_callback=self.view.log,
                        stop_event=self.stop_event
                    )

                    if not success:
                        self.view.log("宏执行失败，已停止", is_error=True)
                        return

                if not (getattr(self, "loop_enabled", False)):
                    break

            if not self.stop_event.is_set():
                self.view.log("宏执行完成")

        except Exception as e:
            self.view.log(f"宏执行出错: {str(e)}", is_error=True)
        finally:
            # 恢复UI状态
            self.view.run_button.config(state="normal")
            self.view.stop_button.config(state="disabled")
            self.stop_event.set()

    def save_undo_state(self):
        """保存撤销状态"""
        if self.model and self.model.current_project:
            import copy
            # 深拷贝当前宏命令列表
            items_copy = [item.to_dict() for item in self.model.get_macro_items()]
            self.undo_stack.append(items_copy)
            # 限制撤销栈大小
            if len(self.undo_stack) > 20:
                self.undo_stack.pop(0)

    def undo_action(self):
        """撤销操作"""
        if not self.undo_stack or not self.model or not self.model.current_project:
            self.view.log("没有可撤销的操作")
            return
        last_state = self.undo_stack.pop()
        # 清空当前列表并恢复
        self.model.current_project.items.clear()
        from macro import KeyboardMacro, TextMacro, MouseMoveMacro, MouseMoveToImageMacro, MouseMacro, ScrollMacro, WaitMacro, WaitKeyMacro
        item_classes = {
            "keyboard": KeyboardMacro,
            "text": TextMacro,
            "mouse_move": MouseMoveMacro,
            "mouse_move_image": MouseMoveToImageMacro,
            "mouse": MouseMacro,
            "scroll": ScrollMacro,
            "wait": WaitMacro,
            "wait_key": WaitKeyMacro
        }
        for item_data in last_state:
            item_type = item_data.get("type")
            item_class = item_classes.get(item_type)
            if item_class:
                self.model.current_project.items.append(item_class.from_dict(item_data))
        self.update_edit_list()
        self.update_macro_list()
        self.view.log("撤销操作")

    def cut_action(self):
        """剪切操作"""
        selected = self.view.edit_listbox.curselection()
        if selected:
            index = selected[0]
            item = self.model.get_macro_item(index)
            if item:
                self.save_undo_state()
                self.clipboard = item.to_dict()
                self.model.remove_macro_item(item.id)
                self.update_edit_list()
                self.update_macro_list()
                self.view.log(f"剪切宏命令: {item.get_display_text()}")

    def copy_action(self):
        """复制操作"""
        selected = self.view.edit_listbox.curselection()
        if selected:
            index = selected[0]
            item = self.model.get_macro_item(index)
            if item:
                self.clipboard = item.to_dict()
                self.view.log(f"复制宏命令: {item.get_display_text()}")

    def paste_action(self):
        """粘贴操作"""
        if self.clipboard and self.model.current_project:
            from macro import KeyboardMacro, TextMacro, MouseMoveMacro, MouseMoveToImageMacro, MouseMacro, ScrollMacro, WaitMacro, WaitKeyMacro
            item_classes = {
                "keyboard": KeyboardMacro,
                "text": TextMacro,
                "mouse_move": MouseMoveMacro,
                "mouse_move_image": MouseMoveToImageMacro,
                "mouse": MouseMacro,
                "scroll": ScrollMacro,
                "wait": WaitMacro,
                "wait_key": WaitKeyMacro
            }
            item_type = self.clipboard.get("type")
            item_class = item_classes.get(item_type)
            if item_class:
                self.save_undo_state()
                new_item = item_class.from_dict(self.clipboard)
                import uuid
                new_item.id = str(uuid.uuid4())  # 新ID
                self.model.current_project.add_item(new_item)
                self.update_edit_list()
                self.update_macro_list()
                self.view.log(f"粘贴宏命令: {new_item.get_display_text()}")

    def show_help(self):
        """显示帮助信息"""
        self.view.show_message(
            "使用帮助",
            "宏自动化工具使用说明:\n\n"
            "1. 编辑模式: 创建和修改宏命令\n"
            "2. 执行模式: 运行宏并查看日志\n"
            "3. 快捷键:\n"
            "   - Ctrl+N: 新建宏工程\n"
            "   - Ctrl+O: 打开宏工程\n"
            "   - Ctrl+S: 保存宏工程\n"
            "   - F9: 运行宏\n"
            "   - F10: 停止宏"
        )

    def show_about(self):
        """显示关于信息"""
        self.view.show_message(
            "关于",
            "宏自动化工具 v20250907.01\n\n"
            "一个用于创建和执行自动化宏的工具\n\n"
            "更新内容：\n"
            "- 修复了文本输入宏在某些环境下无法正常工作的bug"
        )
